home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 151-175 / disk_166 / stevie / source / screen.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  10KB  |  408 lines

  1. /*
  2.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  3.  *
  4.  * Code Contributions By : Tim Thompson           twitch!tjt
  5.  *                         Tony Andrews           onecom!wldrdg!tony 
  6.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  7.  */
  8.  
  9. #include "stevie.h"
  10.  
  11. /*
  12.  * The following variable is set (in cursupdate) to the number of physical
  13.  * lines taken by the line the cursor is on. We use this to avoid extra calls
  14.  * to plines(). The optimized routines updateline() and redrawline()
  15.  * make sure that the size of the cursor line hasn't changed. If so, lines below
  16.  * the cursor will move up or down and we need to call the routines
  17.  * updateNextscreen() and updateRealscreen() to examine the entire screen. 
  18.  */
  19. static int      Cline_size;    /* size (in rows) of the cursor line */
  20. static int      Cline_row;    /* starting row of the cursor line */
  21.  
  22. /*
  23.  * updateline() - like updateNextscreen() but only for cursor line 
  24.  *
  25.  * This determines whether or not we need to call updateNextscreen() to examine the
  26.  * entire screen for changes. This occurs if the size of the cursor line
  27.  * (in rows) hasn't changed.
  28.  */
  29. void
  30. updateline()
  31. {
  32.     int             row, col;
  33.     register char  *screenp;
  34.     LPTR            memp;
  35.     register char  *nextrow;
  36.     char            extra[16];
  37.     int             nextra = 0;
  38.     char            c;
  39.     int             n;
  40.     bool_t          eof;
  41.  
  42.     MustRedrawLine = TRUE;
  43.  
  44. #ifndef AMIGA
  45.     if (MustRedrawScreen) {
  46.     msg("STEVIE internal error: updateline called");
  47.     sleep(5);
  48.     }
  49. #endif
  50.  
  51.     screenp = Nextscreen + (Cline_row * Columns);
  52.  
  53.     memp = *Curschar;
  54.     memp.index = 0;
  55.  
  56.     eof = FALSE;
  57.     col = 0;
  58.     row = Cline_row;
  59.  
  60.     while (!eof) {
  61.  
  62.     /* Get the next character to put on the screen. */
  63.  
  64.     /*
  65.      * The 'extra' array contains the extra stuff that is inserted to
  66.      * represent special characters (tabs, and other non-printable stuff.
  67.      * The order in the 'extra' array is reversed. 
  68.      */
  69.  
  70.     if (nextra > 0)
  71.         c = extra[--nextra];
  72.     else {
  73.         c = gchar(&memp);
  74.         if (inc(&memp) == -1)
  75.         eof = TRUE;
  76.         /*
  77.          * when getting a character from the file, we may have to turn it
  78.          * into something else on the way to putting it into
  79.          * 'Nextscreen'. 
  80.          */
  81.         if (c == TAB && !P(P_LS)) {
  82.         strcpy(extra, "        ");
  83.         /* tab amount depends on current column */
  84.         nextra = ((P(P_TS) - 1) - col % P(P_TS));
  85.         c = ' ';
  86.         } else if (c == NUL && P(P_LS)) {
  87.         extra[0] = NUL;
  88.         nextra = 1;
  89.         c = '$';
  90.         } else if (c != NUL && (n = chars[c].ch_size) > 1) {
  91.         char           *p;
  92.         nextra = 0;
  93.         p = chars[c].ch_str;
  94.         /* copy 'ch-str'ing into 'extra' in reverse */
  95.         while (n > 1)
  96.             extra[nextra++] = p[--n];
  97.         c = p[0];
  98.         }
  99.     }
  100.  
  101.     if (c == NUL) {
  102.         row++;
  103.         /* get pointer to start of next row */
  104.         nextrow = &Nextscreen[row * Columns];
  105.         /* blank out the rest of this row */
  106.         while (screenp != nextrow)
  107.         *screenp++ = ' ';
  108.         col = 0;
  109.         break;
  110.     }
  111.     if (col >= Columns) {
  112.         row++;
  113.         col = 0;
  114.     }
  115.     /* store the character in Nextscreen */
  116.     *screenp++ = c;
  117.     col++;
  118.     }
  119.     if ((row - Cline_row) == Cline_size)
  120.     updateNextscreen();
  121. }
  122.  
  123. /*
  124.  * redrawline 
  125.  *
  126.  * Like updateRealscreen() but only for the cursor line. 
  127.  */
  128. void
  129. redrawline()
  130. {
  131.     register char  *np = Nextscreen + (Cline_row * Columns);
  132.     register char  *rp = Realscreen + (Cline_row * Columns);
  133.     register char  *endline;
  134.     int             row, col;
  135.     int             gorow = -1, gocol = -1;
  136.  
  137.     if (RedrawingDisabled)
  138.     return;
  139.  
  140.     if (!MustRedrawLine && !MustRedrawScreen)
  141.     return;
  142.  
  143.     if (MustRedrawScreen) {
  144.     msg("STEVIE internal error: redrawline called");
  145.     sleep(5);
  146.     }
  147.     endline = np + (Cline_size * Columns);
  148.  
  149.     row = Cline_row;
  150.     col = 0;
  151.  
  152.     outstr(T_CI);        /* disable cursor */
  153.  
  154.     for (; np < endline; np++, rp++) {
  155.     /* If desired screen (contents of Nextscreen) does not */
  156.     /* match what's really there, put it there. */
  157.     if (*np != *rp) {
  158.         /* if we are positioned at the right place, */
  159.         /* we don't have to use windgoto(). */
  160.         if (gocol != col || gorow != row) {
  161.         /*
  162.          * If we're just off by one, don't send an entire esc. seq.
  163.          * (this happens a lot!) 
  164.          */
  165.         if (gorow == row && gocol + 1 == col) {
  166.             outchar(*(np - 1));
  167.             gocol++;
  168.         } else
  169.             windgoto(gorow = row, gocol = col);
  170.         }
  171.         outchar(*rp = *np);
  172.         gocol++;
  173.     }
  174.     if (++col >= Columns) {
  175.         col = 0;
  176.         row++;
  177.     }
  178.     }
  179.     outstr(T_CV);        /* enable cursor again */
  180.  
  181.     MustRedrawScreen = FALSE;
  182. }
  183.  
  184. void
  185. screenclear()
  186. {
  187.     char           *rp, *np;
  188.     char           *end;
  189.  
  190.     outstr(T_ED);        /* clear the display */
  191.  
  192.     rp = Realscreen;
  193.     end = Realscreen + Rows * Columns;
  194.     np = Nextscreen;
  195.  
  196.     /* blank out the stored screens */
  197.     while (rp != end)
  198.     *rp++ = *np++ = ' ';
  199. }
  200.  
  201. void
  202. cursupdate()
  203. {
  204.     LPTR           *p;
  205.     char            c;
  206.     int             incr, nlines;
  207.     int             i;
  208.     int             didincr;
  209.  
  210.     if (bufempty()) {        /* special case - file is empty */
  211.     *Topchar = *Filemem;
  212.     *Curschar = *Filemem;
  213.     } else if (LINEOF(Curschar) < LINEOF(Topchar)) {
  214.     nlines = cntllines(Curschar, Topchar);
  215.     /*
  216.      * if the cursor is above the top of the screen, put it at the top of
  217.      * the screen.. 
  218.      */
  219.     *Topchar = *Curschar;
  220.     Topchar->index = 0;
  221.     /*
  222.      * ... and, if we weren't very close to begin with, we scroll so that
  223.      * the line is close to the middle. 
  224.      */
  225.     if (nlines > Rows / 3) {
  226.         for (i = 0, p = Topchar; i < Rows / 3; i++, *Topchar = *p)
  227.         if ((p = prevline(p)) == NULL)
  228.             break;
  229.     } else
  230.         s_ins(0, nlines - 1);
  231.     updateNextscreen();
  232.     } else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
  233.     nlines = cntllines(Botchar, Curschar);
  234.     /*
  235.      * If the cursor is off the bottom of the screen, put it at the top
  236.      * of the screen.. ... and back up 
  237.      */
  238.     if (nlines > Rows / 3) {
  239.         p = Curschar;
  240.         for (i = 0; i < (2 * Rows) / 3; i++)
  241.         if ((p = prevline(p)) == NULL)
  242.             break;
  243.         *Topchar = *p;
  244.     } else {
  245.         scrollup(nlines);
  246.     }
  247.     updateNextscreen();
  248.     }
  249.     Cursrow = Curscol = Cursvcol = 0;
  250.     for (p = Topchar; p->linep != Curschar->linep; p = nextline(p))
  251.     Cursrow += plines(p);
  252.  
  253.     Cline_row = Cursrow;
  254.     Cline_size = plines(p);
  255.  
  256.     for (i = 0; i <= Curschar->index; i++) {
  257.     c = Curschar->linep->s[i];
  258.     /* A tab gets expanded, depending on the current column */
  259.     if (c == TAB && !P(P_LS))
  260.         incr = P(P_TS) - (Curscol % P(P_TS));
  261.     else
  262.         incr = chars[c].ch_size;
  263.     Curscol += incr;
  264.     Cursvcol += incr;
  265.     if (Curscol >= Columns) {
  266.         Curscol -= Columns;
  267.         Cursrow++;
  268.         didincr = TRUE;
  269.     } else
  270.         didincr = FALSE;
  271.     }
  272.     if (didincr)
  273.     Cursrow--;
  274.  
  275.     if (c == TAB && State == NORMAL && !P(P_LS)) {
  276.     Curscol--;
  277.     Cursvcol--;
  278.     } else {
  279.     Curscol -= incr;
  280.     Cursvcol -= incr;
  281.     }
  282.     if (Curscol < 0)
  283.     Curscol += Columns;
  284.  
  285.     if (set_want_col) {
  286.     Curswant = Cursvcol;
  287.     set_want_col = FALSE;
  288.     }
  289. }
  290.  
  291. /*
  292.  * The rest of the routines in this file perform screen manipulations. The
  293.  * given operation is performed physically on the screen. The corresponding
  294.  * change is also made to the internal screen image. In this way, the editor
  295.  * anticipates the effect of editing changes on the appearance of the screen.
  296.  * That way, when we call screenupdate a complete redraw isn't usually
  297.  * necessary. Another advantage is that we can keep adding code to anticipate
  298.  * screen changes, and in the meantime, everything still works. 
  299.  */
  300.  
  301. /*
  302.  * s_ins(row, nlines) - insert 'nlines' lines at 'row' 
  303.  */
  304. void
  305. s_ins(row, nlines)
  306.     int             row;
  307.     int             nlines;
  308. {
  309.     char           *s, *d;    /* src & dest for block copy */
  310.     char           *e;        /* end point for copy */
  311.     int             i;
  312.  
  313.     if ((T_IL[0] == NUL) || RedrawingDisabled || nlines <= 0)
  314.     return;
  315.  
  316.     /*
  317.      * It "looks" better if we do all the inserts at once 
  318.      */
  319.     outstr(T_SC);        /* save position */
  320.  
  321.     if (T_IL_B[0] == NUL) {
  322.     for (i = 0; i < nlines; i++) {
  323.         windgoto(row, 0);
  324.         outstr(T_IL);
  325.     }
  326.     } else {
  327.     windgoto(row, 0);
  328.     outstr(T_IL);
  329.     if (nlines >= 10)
  330.         outchar((char) (nlines / 10 + '0'));
  331.     outchar((char) (nlines % 10 + '0'));
  332.     outstr(T_IL_B);
  333.     }
  334.  
  335.     windgoto(Rows - 1, 0);    /* delete any garbage that may have */
  336.     outstr(T_EL);        /* been shifted to the bottom line */
  337.  
  338.     outstr(T_RC);        /* restore the cursor position */
  339.  
  340.     /*
  341.      * Now do a block move to update the internal screen image 
  342.      */
  343.     d = Realscreen + (Columns * (Rows - 1)) - 1;
  344.     s = d - (Columns * nlines);
  345.     e = Realscreen + (Columns * row);
  346.  
  347.     while (s >= e)
  348.     *d-- = *s--;
  349.  
  350.     /*
  351.      * Clear the inserted lines 
  352.      */
  353.     s = Realscreen + (row * Columns);
  354.     e = s + (nlines * Columns);
  355.     while (s < e)
  356.     *s++ = ' ';
  357. }
  358.  
  359. /*
  360.  * s_del(row, nlines) - delete 'nlines' lines at 'row' 
  361.  */
  362. void
  363. s_del(row, nlines)
  364.     int             row;
  365.     int             nlines;
  366. {
  367.     char           *s, *d, *e;
  368.     int             i;
  369.  
  370.     if ((T_DL[0] == NUL) || RedrawingDisabled || nlines <= 0)
  371.     return;
  372.  
  373.     outstr(T_SC);        /* save position */
  374.  
  375.     windgoto(Rows - 1, 0);    /* delete any garbage that */
  376.     outstr(T_EL);        /* was on the status line */
  377.  
  378.     /* delete the lines */
  379.     if (T_DL_B[0] == NUL) {
  380.     for (i = 0; i < nlines; i++) {
  381.         windgoto(row, 0);
  382.         outstr(T_DL);    /* delete a line */
  383.     }
  384.     } else {
  385.     windgoto(row, 0);
  386.     outstr(T_DL);
  387.     if (nlines >= 10)
  388.         outchar((char) (nlines / 10 + '0'));
  389.     outchar((char) (nlines % 10 + '0'));
  390.     outstr(T_DL_B);
  391.     }
  392.  
  393.     outstr(T_RC);        /* restore position */
  394.  
  395.     /*
  396.      * do a block move to update the internal image 
  397.      */
  398.     d = Realscreen + (row * Columns);
  399.     s = d + (nlines * Columns);
  400.     e = Realscreen + ((Rows - 1) * Columns);
  401.  
  402.     while (s < e)
  403.     *d++ = *s++;
  404.  
  405.     while (d < e)        /* clear the lines at the bottom */
  406.     *d++ = ' ';
  407. }
  408.